---
title: Providers
---

import creatingProvider from "./providers/creating_a_provider";
import declaringManyProviders from "./providers/declaring_many_providers";
import {
  trimSnippet,
  AutoSnippet,
  When,
} from "../../src/components/CodeSnippet";
import { Link } from "../../src/components/Link";

Now that we have installed [Riverpod], let's talk about "providers".

Providers are the most important part of a [Riverpod] application.
A provider is an object that encapsulates a piece of state and allows listening
to that state.

## Why use providers?

Wrapping a piece of state in a provider:

- Allows easily accessing that state in multiple locations.
  Providers are a complete replacement for patterns like Singletons,
  Service Locators, Dependency Injection or InheritedWidgets.

- Simplifies combining this state with others.
  Ever struggled to merge multiple objects into one? This scenario is built
  directly inside providers.

- Enables performance optimizations.
  Whether for filtering widget rebuilds or for caching expensive state computations;
  providers ensure that only what is impacted by a state change is recomputed.

- Increases the testability of your application.
  With providers, you do not need complex `setUp`/`tearDown` steps. Furthermore,
  any provider can be overridden to behave differently during a test, which
  allows easily testing a very specific behavior.

- Allows easy integration with advanced features, such as logging or
  pull-to-refresh.

## Creating a provider

Providers come in many variants, but they all work the same way.

The most common usage is to declare them as global constants like so:

<AutoSnippet language="dart" {...creatingProvider}></AutoSnippet>

:::note
Do not be frightened by the global aspect of providers.
Providers are fully immutable. Declaring a provider is no different from declaring
a function, and providers are testable and maintainable.
:::

This snippet consists of three components:

- `final myProvider`, the declaration of a variable.
  This variable is what we will use in the future to read the state of our provider.
  Providers should always be `final`.

- `Provider`, the provider that we decided to use.
  [Provider] is the most basic of all providers. It exposes an object that never
  changes.
  We could replace [Provider] with other providers like [StreamProvider] or
  [NotifierProvider], to change how the value is interacted with.

- A function that creates the shared state.
  That function will always receive an object called `ref` as a parameter. This object
  allows us to read other providers, perform some operations when the state
  of our provider will be destroyed, and much more.

The type of the object returned by the function passed to a provider depends on
the provider used.
For example, the function of a [Provider] can create any object.
On the other hand, [StreamProvider]'s callback will be expected to return a [Stream].

:::info
You can declare as many providers as you want without limitations.
As opposed to when using `package:provider`, [Riverpod] allows creating multiple
providers exposing a state of the same "type":

<AutoSnippet language="dart" {...declaringManyProviders}></AutoSnippet>

The fact that both providers create a `String` does not cause any problem.
:::

:::caution
For providers to work, you must add [ProviderScope] at the root of your
Flutter applications:

```dart
void main() {
  runApp(ProviderScope(child: MyApp()));
}
```

:::

## Different Types of Providers

There are multiple types of providers for multiple different use cases.

With all of these providers available, it is sometimes difficult to understand when to use one provider type over another.
Use the table below to choose a provider that fits what you want to provide to the widget tree.

| Provider Type            | Provider Create Function              | Example Use Case                                                                                      |
| ------------------------ | ------------------------------------- | ----------------------------------------------------------------------------------------------------- |
| [Provider]               | Returns any type                      | A service class / computed property (filtered list)                                                   |
| [StateProvider]          | Returns any type                      | A filter condition / simple state object                                                              |
| [FutureProvider]         | Returns a Future of any type          | A result from an API call                                                                             |
| [StreamProvider]         | Returns a Stream of any type          | A stream of results from an API                                                                       |
| [NotifierProvider]       | Returns a subclass of (Async)Notifier | A complex state object that is immutable except through an interface                                  |
| [StateNotifierProvider]  | Returns a subclass of StateNotifier   | A complex state object that is immutable except through an interface. Prefer using a notifierProvider |
| [ChangeNotifierProvider] | Returns a subclass of ChangeNotifier  | A complex state object that requires mutability                                                       |

:::caution
While all providers have their purpose, [ChangeNotifierProvider]s are not recommended for scalable applications. See <Link documentID="concepts/why_immutability" />. It exists in the
`flutter_riverpod` package to provide an easy migration path from
`package:provider`, and allows for some flutter specific use-cases such as
integration with some Navigator 2 packages. :::

## Provider Modifiers

All Providers have a built-in way to add extra functionalities to your different providers.

They may add new features to the `ref` object or change slightly how the provider
is consumed.
Modifiers can be used on all providers, with a syntax similar to named constructor:

```dart
final myAutoDisposeProvider = StateProvider.autoDispose<int>((ref) => 0);
final myFamilyProvider = Provider.family<String, int>((ref, id) => '$id');
```

At the moment, there are two modifiers available:

- <Link documentID="concepts/modifiers/auto_dispose" />, which will make the
  provider automatically destroy its state when it is no longer being listened
  to.
- <Link documentID="concepts/modifiers/family" />, which allows creating a
  provider from external parameters.

:::note
A provider can use multiple modifiers at once:

```dart
final userProvider = FutureProvider.autoDispose.family<User, int>((ref, userId) async {
  return fetchUser(userId);
});
```

:::

That's it for this guide!

You can continue with <Link documentID="concepts/reading"/>.
Alternatively, you can see <Link documentID="concepts/combining_providers"/>.

[get_it]: http://pub.dev/packages/get_it
[inheritedwidget]: https://api.flutter.dev/flutter/widgets/InheritedWidget-class.html
[stream]: https://api.dart.dev/stable/2.8.4/dart-async/Stream-class.html
[ondispose]: https://pub.dev/documentation/riverpod/latest/riverpod/Ref/onDispose.html
[riverpod]: https://github.com/rrousselgit/riverpod
[hooks_riverpod]: https://pub.dev/packages/hooks_riverpod
[flutter_riverpod]: https://pub.dev/packages/flutter_riverpod
[flutter_hooks]: https://github.com/rrousselGit/flutter_hooks
[provider]: /docs/providers/provider
[streamprovider]: /docs/providers/stream_provider
[futureprovider]: /docs/providers/future_provider
[stateprovider]: /docs/providers/state_provider
[statenotifierprovider]: /docs/providers/state_notifier_provider
[notifierProvider]: /docs/providers/notifier_provider
[changenotifierprovider]: https://pub.dev/documentation/flutter_riverpod/latest/flutter_riverpod/ChangeNotifierProvider-class.html
[providerscope]: https://pub.dev/documentation/flutter_riverpod/latest/flutter_riverpod/ProviderScope-class.html
